﻿using ACC.Extensions.ClientBusiness;
using ACC.Extensions.Entities;
using ACC.Extensions.PCClient.Helper;
using ACC.Extensions.Utilities;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
using System.Windows;
using System.Windows.Threading;
using System.Xml;

namespace ACC.Extensions.PCClient
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        System.Threading.Mutex mutex;
        public App()
        {
            this.Startup += new StartupEventHandler(App_Startup);
            this.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        }
        void App_Startup(object sender, StartupEventArgs e)
        {
            bool ret;
            mutex = new System.Threading.Mutex(true, "ElectronicNeedleTherapySystem", out ret);

            if (!ret)
            {
                // MessageBox.Show("已有一个程序实例运行");
                Environment.Exit(0);
            }

        }
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            if (AppConfigHelper.GetAppSettings("DebugMode").ToString() == "1")  // 非debug模式
            {
                //检查是否需要更新
                CheckUpdateProcess();
                //如果不是管理员，程序会直接退出，并使用管理员身份重新运行(由于需要同步系统时间)
                CheckAdministrator();
            }

            //启动后设置语言
            string lang = AppConfigHelper.GetAppSettings("cn");

            if (lang != null)
            {
                switch (lang.Trim().ToLower())
                {
                    case "cn":
                        LanguageHelper.SelectChinese();
                        break;
                    case "en":
                    default:
                        LanguageHelper.SelectEnglish();
                        break;
                }
            }
            //启动后读取配置文件
            UISession.ClientSetting = ClientSettingHelper.ReadSetting();
            if (UISession.ClientSetting == null)
                UISession.ClientSetting = new LocalSetting();

            UISession.PartTypePicList = ClientSettingHelper.ReadPicList();
            if (UISession.PartTypePicList == null)
            {
                UISession.PartTypePicList = new List<PartTypePic>();
            }
        }

        //AppDomain.UnhandledException 事件--当某个异常未被捕获时出现。主要指的是非UI线程。
        void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            e.Handled = true;
            Log4Helper.Error(null, e.Exception);
            MessageBox.Show(e.Exception.Message);
            Application.Current.Shutdown();
        }

        // Application.DispatcherUnhandledException 事件--如果异常是由应用程序引发，但未处理，发生。主要指的是UI线程。
        void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject is System.Exception)
            {
                Log4Helper.Error(null, (System.Exception)e.ExceptionObject);
                MessageBox.Show(((System.Exception)e.ExceptionObject).Message);
            }
        }


        /// 检查是否是管理员身份  
        /// </summary>  
        private void CheckAdministrator()
        {
            var wi = WindowsIdentity.GetCurrent();
            var wp = new WindowsPrincipal(wi);

            bool runAsAdmin = wp.IsInRole(WindowsBuiltInRole.Administrator);

            if (!runAsAdmin)
            {
                // It is not possible to launch a ClickOnce app as administrator directly,  
                // so instead we launch the app as administrator in a new process.  
                var processInfo = new ProcessStartInfo(Assembly.GetExecutingAssembly().CodeBase);

                // The following properties run the new process as administrator  
                processInfo.UseShellExecute = true;
                processInfo.Verb = "runas";

                // Start the new process  
                try
                {
                    Process.Start(processInfo);
                }
                catch (Exception ex)
                {
                    //ex.WriteLog();
                }

                // Shut down the current process  
                Environment.Exit(0);
            }
        }

        protected void CheckUpdateProcess()
        {
            string appPath = System.AppDomain.CurrentDomain.BaseDirectory;
            XmlHelper xmlHelper = new XmlHelper();
            XmlNode nodeUrl = xmlHelper.GetXmlNodeByXpath(appPath + "UpdateList.xml", "/AutoUpdater/Updater/Url");
            if (nodeUrl == null) return;
            string UpdateFileUrl = nodeUrl.InnerText.Trim();

            XmlNode nodeVersion = xmlHelper.GetXmlNodeByXpath(appPath + "UpdateList.xml", "/AutoUpdater/Updater/Version");
            if (nodeVersion == null) return;
            string CurrentVersion = nodeVersion.InnerText.Trim();

            XmlNode nodeEntryPoint = xmlHelper.GetXmlNodeByXpath(appPath + "UpdateList.xml", "/AutoUpdater/Updater/EntryPoint");
            if (nodeEntryPoint == null) return;
            string ExeName = nodeEntryPoint.InnerText.Trim();

            if (!string.IsNullOrEmpty(UpdateFileUrl) && File.Exists(UpdateFileUrl))
            {
                string FileMd5 = GetFileMD5(UpdateFileUrl);
                string ServerUpdateList = UpdateFileUrl.Substring(0, UpdateFileUrl.LastIndexOf("\\")) + "\\UpdateList.xml";
                if (!string.IsNullOrEmpty(ServerUpdateList) && File.Exists(ServerUpdateList))
                {
                    string NewVersion = xmlHelper.GetXmlNodeByXpath(ServerUpdateList, "/AutoUpdater/Updater/Version").InnerText.Trim();

                    if (new Version(NewVersion) > new Version(CurrentVersion))
                    {
                        string args = CurrentVersion + " ";
                        args = args + NewVersion + " ";
                        args = args + appPath + " ";
                        args = args + UpdateFileUrl + " ";
                        args = args + ExeName + " ";
                        args = args + FileMd5;
                        System.Diagnostics.Process process = new System.Diagnostics.Process();
                        process.StartInfo.FileName = "AutoUpdate.exe";
                        process.StartInfo.Arguments = args;
                        process.StartInfo.WorkingDirectory = appPath + "AutoUpdate";//要掉用得exe路径例如:"C:\windows";                 
                        process.StartInfo.CreateNoWindow = true;
                        // Start the new process  
                        try
                        {
                            process.Start();
                        }
                        catch (Exception ex)
                        {
                            //ex.WriteLog();
                            return;
                        }

                        // Shut down the current process  
                        Environment.Exit(0);
                    }
                }
            }
        }

        private static string GetFileMD5(string fileName)
        {
            try
            {
                var file = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                var md5 = new MD5CryptoServiceProvider();
                var retVal = md5.ComputeHash(file);
                file.Close();
                var sb = new StringBuilder();
                for (var i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                return string.Empty;
            }
        }
    }
}
